/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.reviewerplugin;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.LayoutStyle;

import com.pearreview.application.Messages;
import com.pearreview.application.PluginAdapter;
import com.pearreview.application.FileHistory.ChangeEvent;
import com.pearreview.application.FileHistory.ChangeListener;
import com.pearreview.ui.FileMenuItem;
import com.pearreview.ui.BottomButtonPanel;
import com.pearreview.ui.CompletableJTextField;
import com.pearreview.ui.FadingTextArea;
import com.pearreview.ui.HeadingLabel;
import com.pearreview.util.XMLFileFilter;
import com.pearreview.util.review.Product;
import com.pearreview.util.review.Review;
import com.pearreview.util.review.io.ReviewReader;
import com.pearreview.util.review.io.XMLReviewReader;

/**
 * This panel contains the general information of the review and product.
 * The user is able to import information from a existing review
 * XML file.
 *
 */
public class InformationPanel extends ReviewerPanel {

	private static final long serialVersionUID = 5770082743822688184L;
	
	public final static String REVIEW_HISTORY_TYPE = "review-xml";
	
	private JLabel reviewNameLabel;
	private CompletableJTextField reviewName;
	private JLabel ReviewDescriptionLabel;
	private JScrollPane scrollPaneReviewDescription;
	private FadingTextArea reviewDescription;
	private JLabel reviewCommentsLabel;
	private JScrollPane scrollPaneReviewComments;
	private FadingTextArea reviewComments;
	private JSeparator separatorReviewProduct;
	private JLabel productNameLabel;
	private CompletableJTextField productName;
	private JLabel productVersionLabel;
	private CompletableJTextField productVersion;
	
	private JButton popupReviewButton;
	private JPopupMenu reviewFilePopup;
	private JSeparator separatorProductImport;
	private JLabel readReviewPanelLabel;
   
	private Product product;
	private Report report;
	
	private BottomButtonPanel bottom;
	
	private PluginAdapter pluginAdapter;
	
	private Action readReviewAction = new ReadReviewAction();

	public InformationPanel(PluginAdapter pa) {
		pluginAdapter = pa;
		initComponents();
	}
	
	public PluginAdapter getPluginAdapter() {
		return pluginAdapter;
	}
	
	@Override
	public void applyReport() {
		if(report == null) {
			report = new Report();
		}
	   
		report.setName(getReviewName());
		report.setDescription(getReviewDescription());
		report.setComments(getReviewComments());
		report.setProduct(getProduct());
	}

	@Override
	public void setNextViewAction(Action action) {
		bottom.setNextViewAction(action);
	}
	
	@Override
	public void setPreviousViewAction(Action action) {
		bottom.setPreviousViewAction(action);

	}

	@Override
	public void setReport(Report report) {
		this.report = report;
		if (report != null) {
			setReviewName(report.getName());
			setReviewDescription(report.getDescription());
			setReviewComments(report.getComments());
			setProduct(report.getProduct());
		} else {
			setReviewName(null);
			setReviewDescription(null);
			setReviewComments(null);
			setProduct(null);
		}
	}
	
	public void setReviewName(String reviewName) {
		this.reviewName.setText(reviewName);
	}
	
	public String getReviewName() {
		return this.reviewName.getText();
	}
	
	public void setReviewDescription(String reviewDescription) {
		this.reviewDescription.setText(reviewDescription);
	}
	
	public String getReviewDescription() {
		return this.reviewDescription.getText();
	}
	
	public void setReviewComments(String reviewComments) {
		this.reviewComments.setText(reviewComments);
	}
	
	public String getReviewComments() {
		return this.reviewComments.getText();
	}
	
	public void setProduct(Product product) {
		this.product = product;
		
		if(product != null) {
			productName.setText(product.getName());
			productVersion.setText(product.getVersion());
		} else {
			productName.setText(null);
			productVersion.setText(null);
		}
	}
	
	public Product getProduct() {
		if(product == null) {
			product = new Product();
		}
	   
		product.setName(productName.getText());
		product.setVersion(productVersion.getText());
	   
		return product;
	}

	private void initComponents() {
		
		setFont(new Font("Tahoma", Font.PLAIN, 12));
			   
		reviewNameLabel = new JLabel();
		reviewName = new CompletableJTextField();
		ReviewDescriptionLabel = new JLabel();
		scrollPaneReviewDescription = new JScrollPane();
		reviewDescription = new FadingTextArea();
		reviewCommentsLabel = new JLabel();
		scrollPaneReviewComments = new JScrollPane();
		reviewComments = new FadingTextArea();
		separatorReviewProduct = new JSeparator();
		productNameLabel = new JLabel();
		productName = new CompletableJTextField();
		productVersionLabel = new JLabel();
		productVersion = new CompletableJTextField();
		JPanel formPanel = new JPanel();
		  
		setLayout(new BorderLayout());
		formPanel.setOpaque(false);
			   
		setBackground(new Color(214, 214, 214));
		
		//---- reviewFileHistoryPopup ----
		reviewFilePopup = new JPopupMenu();
		reviewFilePopup.setFont(getFont());
		add(reviewFilePopup);
		ChangeListener changeListener = new ChangeListener() {
			private static final long serialVersionUID = -1012481549851472601L;
			@Override
			public void typeChanged(ChangeEvent ce) {
				int size = getPluginAdapter().getFileHistory()
						.getFiles(REVIEW_HISTORY_TYPE).size();
				popupReviewButton.setEnabled(size > 0);
						
			}
		};
		getPluginAdapter().getFileHistory().addChangeListener(changeListener);
		
		//---- readReviewPanel ----
		JPanel readReviewPanel = new JPanel();
		JButton readReviewButton = new JButton(readReviewAction);
		popupReviewButton = new JButton(">");
		readReviewPanel.setOpaque(false);
		GroupLayout readReviewLayout = new GroupLayout(readReviewPanel);
		readReviewPanel.setLayout(readReviewLayout);
		readReviewLayout.setHorizontalGroup(
				readReviewLayout.createSequentialGroup()
						.addComponent(readReviewButton)
						.addComponent(popupReviewButton));
		readReviewLayout.setVerticalGroup(
				readReviewLayout.createParallelGroup()
						.addComponent(readReviewButton)
						.addComponent(popupReviewButton));
		int size = getPluginAdapter().getFileHistory()
				.getFiles(REVIEW_HISTORY_TYPE).size();
		popupReviewButton.setEnabled(size > 0);
		
		popupReviewButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				popupReviewFileHistory();
			}
		});
		  
		//---- separatorReviewProduct ----
		separatorReviewProduct.setBackground(new Color(0x828790));
		separatorReviewProduct.setForeground(new Color(0xd4d4d4));
		
		//---- reviewNameLabel ----
		reviewNameLabel.setText(Messages.getString(
						"PearReview.Moderator.review.name"));
		reviewNameLabel.setFont(getFont());
		
		//---- reviewName ----
		reviewName.setFont(new Font("Tahoma", Font.PLAIN, 12));
		reviewName.setBorder(BorderFactory.createMatteBorder(
								1, 1, 1, 1, new Color(0x828790)));

		//---- ReviewDescriptionLabel ----
		ReviewDescriptionLabel.setText(Messages.getString(
				"PearReview.Moderator.review.description"));
		ReviewDescriptionLabel.setFont(getFont());

		//======== scrollPaneReviewDescription ========
		{
			//---- reviewDescription ----
			reviewDescription.setFont(getFont());
			reviewDescription.setLineWrap(true);
			scrollPaneReviewDescription.setViewportView(reviewDescription);
		}

		//---- reviewCommentsLabel ----
		reviewCommentsLabel.setText(Messages.getString(
				"PearReview.Moderator.review.comments"));
		reviewCommentsLabel.setFont(getFont());
		
		//======== scrollPaneReviewComments ========
		{
			//---- reviewComments ----
			reviewComments.setFont(getFont());
			reviewComments.setLineWrap(true);
			scrollPaneReviewComments.setViewportView(reviewComments);
		}

		//---- productNameLabel ----
		productNameLabel.setText(Messages.getString(
				"PearReview.Moderator.product.name"));
		productNameLabel.setFont(getFont());
		
		//---- productName ----
		productName.setFont(getFont());
		productName.setBorder(BorderFactory.createMatteBorder(
				1, 1, 1, 1, new Color(0x828790)));

		//---- productVersionLabel ----
		productVersionLabel.setText(Messages.getString(
				"PearReview.Moderator.product.version"));
		productVersionLabel.setFont(getFont());

		//---- productVersion ----
		productVersion.setFont(getFont());
		productVersion.setBorder(BorderFactory.createMatteBorder(
				1, 1, 1, 1, new Color(0x828790)));
		
		separatorProductImport = new JSeparator();
		separatorProductImport.setBackground(new Color(0x828790));
		separatorProductImport.setForeground(new Color(0xd4d4d4));
		
		readReviewPanelLabel = new JLabel();
		readReviewPanelLabel.setText(Messages.getString(
				"PearReview.Reviewer.information.import"));
		readReviewPanelLabel.setFont(getFont());
			   
		GroupLayout layout = new GroupLayout(formPanel);
		formPanel.setLayout(layout);
		layout.setHorizontalGroup(
			layout.createSequentialGroup()
				.addContainerGap()
				.addGroup(layout.createParallelGroup()
						.addComponent(separatorReviewProduct,
								GroupLayout.Alignment.TRAILING,
								GroupLayout.DEFAULT_SIZE,
								657,
								GroupLayout.PREFERRED_SIZE)
						.addComponent(separatorProductImport,
								GroupLayout.Alignment.TRAILING,
								GroupLayout.DEFAULT_SIZE,
								657,
								GroupLayout.PREFERRED_SIZE)
						.addGroup(GroupLayout.Alignment.LEADING,
								layout.createSequentialGroup()
						.addGroup(layout.createParallelGroup()
						.addComponent(reviewNameLabel,
								GroupLayout.Alignment.LEADING,
								GroupLayout.DEFAULT_SIZE,
								80,
								GroupLayout.PREFERRED_SIZE)
						.addComponent(ReviewDescriptionLabel,
							GroupLayout.Alignment.LEADING,
								GroupLayout.DEFAULT_SIZE,
								80,
								GroupLayout.PREFERRED_SIZE)
						.addComponent(reviewCommentsLabel,
								GroupLayout.Alignment.LEADING,
								GroupLayout.DEFAULT_SIZE,
								80,
								GroupLayout.PREFERRED_SIZE))
						.addGap(57, 57, 57)
						.addGroup(layout.createParallelGroup(
								GroupLayout.Alignment.TRAILING)
						.addComponent(scrollPaneReviewComments,
								GroupLayout.Alignment.LEADING,
								GroupLayout.DEFAULT_SIZE,
								520,
								GroupLayout.PREFERRED_SIZE)
						.addComponent(scrollPaneReviewDescription,
								GroupLayout.Alignment.LEADING,
								GroupLayout.DEFAULT_SIZE,
								520,
								GroupLayout.PREFERRED_SIZE)
						.addComponent(reviewName,
								GroupLayout.Alignment.LEADING,
								GroupLayout.PREFERRED_SIZE,
								300,
								GroupLayout.PREFERRED_SIZE)
						))
						.addGroup(layout.createSequentialGroup()
								.addGroup(layout.createParallelGroup()
						.addComponent(productNameLabel,
								GroupLayout.Alignment.LEADING,
								GroupLayout.DEFAULT_SIZE,
								80,
								GroupLayout.PREFERRED_SIZE)
						.addComponent(productVersionLabel,
								GroupLayout.Alignment.LEADING,
								GroupLayout.DEFAULT_SIZE,
								80,
								GroupLayout.PREFERRED_SIZE)
						.addComponent(readReviewPanelLabel,
								GroupLayout.Alignment.LEADING,
								GroupLayout.DEFAULT_SIZE,
								80,
								GroupLayout.PREFERRED_SIZE))
						.addGap(50, 50, 50)
						.addGroup(layout.createParallelGroup()
						.addComponent(readReviewPanel,
								GroupLayout.DEFAULT_SIZE,
									300,
									GroupLayout.PREFERRED_SIZE)
						.addComponent(productVersion,
							GroupLayout.DEFAULT_SIZE,
								300,
								GroupLayout.PREFERRED_SIZE)
						.addComponent(productName,
								GroupLayout.DEFAULT_SIZE,
								300,
								GroupLayout.PREFERRED_SIZE)))));
		layout.setVerticalGroup(
				layout.createParallelGroup()
						.addGroup(layout.createSequentialGroup()
								.addContainerGap()
								.addGroup(layout.createParallelGroup(
										GroupLayout.Alignment.BASELINE)
								.addComponent(reviewNameLabel)
								.addComponent(reviewName,
										 GroupLayout.PREFERRED_SIZE,
										 GroupLayout.DEFAULT_SIZE,
										 GroupLayout.PREFERRED_SIZE))
						 .addPreferredGap(LayoutStyle
								 .ComponentPlacement.UNRELATED)
						 .addGroup(layout.createParallelGroup()
								 .addComponent(ReviewDescriptionLabel)
										 .addComponent(
												 scrollPaneReviewDescription,
												 GroupLayout.PREFERRED_SIZE,
												 70,
												 GroupLayout.PREFERRED_SIZE))
								 .addGap(15, 15, 15)
								 .addGroup(layout.createParallelGroup()
										 .addComponent(reviewCommentsLabel)
										 .addComponent(
												 scrollPaneReviewComments,
												 GroupLayout.PREFERRED_SIZE,
												 70,
												 GroupLayout.PREFERRED_SIZE))
										.addGap(18, 18, 18)
										.addComponent(separatorReviewProduct,
												 GroupLayout.PREFERRED_SIZE,
												 GroupLayout.DEFAULT_SIZE,
												 GroupLayout.PREFERRED_SIZE)
										.addGap(18)
										.addGroup(layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
										.addComponent(productNameLabel)
										.addComponent(productName,
												GroupLayout.PREFERRED_SIZE,
												GroupLayout.DEFAULT_SIZE,
												GroupLayout.PREFERRED_SIZE))
										.addPreferredGap(LayoutStyle
												.ComponentPlacement.UNRELATED)
										.addGroup(layout.createParallelGroup(
														GroupLayout.Alignment
														.BASELINE)
												.addComponent(
														productVersionLabel)
										.addComponent(productVersion,
												 GroupLayout.PREFERRED_SIZE,
												 GroupLayout.DEFAULT_SIZE,
												 GroupLayout.PREFERRED_SIZE))
										.addGap(18)
										.addComponent(separatorProductImport,
												 GroupLayout.PREFERRED_SIZE,
												 GroupLayout.DEFAULT_SIZE,
												 GroupLayout.PREFERRED_SIZE)
										.addGap(18)
										.addGroup(layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
										.addComponent(readReviewPanelLabel)
										.addComponent(readReviewPanel,
												GroupLayout.PREFERRED_SIZE,
												GroupLayout.DEFAULT_SIZE,
												GroupLayout.PREFERRED_SIZE))
										));
		
		add(formPanel, BorderLayout.CENTER);
		add(new HeadingLabel(Messages.getString(
						"PearReview.Reviewer.tabs.information")), 
						BorderLayout.NORTH);
		bottom = new BottomButtonPanel();
		add(bottom, BorderLayout.SOUTH);
	}
	
	public void readReview() {
		final JFileChooser openDialog = new JFileChooser();
		openDialog.setMultiSelectionEnabled(false);
		
		openDialog.setFileFilter(new XMLFileFilter());
		
		pluginAdapter.getSpringGlassPane().setFaded(true);
		int ret = openDialog.showOpenDialog(this);
		pluginAdapter.getSpringGlassPane().setFaded(false);
			 
		if (JFileChooser.APPROVE_OPTION != ret)
			return;
				 
		File f = openDialog.getSelectedFile();
				 
		if (f.isFile() && f.canRead()) {
			readReview(f);
		}
	}
	
	public void readReview(File file) {
		try {
			ReviewReader reader = new XMLReviewReader();
			Review review = reader.read(file);
			
			if(report != null) {
				report.setAspects(review.getAspects());
				
				report.setSeverities(review.getSeverities());
				
				report.setProduct(review.getProduct());
				setProduct(review.getProduct());
				
				report.setName(review.getName());
				setReviewName(review.getName());
				
				report.setDescription(review.getDescription());
				setReviewDescription(review.getDescription());
				
				report.setComments(review.getComments());
				setReviewComments(review.getComments());
			}
		} catch(Throwable e) {
			JOptionPane.showMessageDialog(this,
					e.getMessage(), 
					Messages.getString("PearReview.error"), 
					JOptionPane.ERROR_MESSAGE);
		}
	}
	
	public void popupReviewFileHistory() {
		reviewFilePopup.removeAll();
		
		List<File> files = getPluginAdapter().getFileHistory()
				.getFiles(REVIEW_HISTORY_TYPE);
		
		for(int i = 0 ; i < files.size() ; i++) {
			File file = files.get(i);
			
			final FileMenuItem item = new FileMenuItem(file, 0x31 + i );
			item.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					readReview(item.getFile());
				}
			});
			reviewFilePopup.add(item);
		}
		
		reviewFilePopup.addSeparator();
		reviewFilePopup.add(readReviewAction);
		
		reviewFilePopup.show(popupReviewButton, 
				popupReviewButton.getWidth(), 
				0);
	}
	
	protected class ReadReviewAction extends AbstractAction {
		private static final long serialVersionUID = -2800146451592324430L;
		public ReadReviewAction() {
			putValue(Action.NAME, Messages.getString(
					"PearReview.Reviewer.information.browse"));
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			readReview();
		}
	}
}